package com.woniu.teachmall.service;

import io.minio.*;
import io.minio.http.Method;
import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * MinIO对象存储服务
 * 提供文件上传、访问、校验及删除等核心功能
 */
@Service
public class MinioService {
    // MinIO客户端实例（由Spring Boot自动配置）
    @Autowired
    private MinioClient minioClient;

    // 存储桶名称（从配置文件注入）
    @Value("${minio.bucketName}")
    private String bucketName;

    // MinIO服务端点（从配置文件注入）
    @Value("${minio.endpoint}")
    private String endpoint;

    /**
     * 上传MultipartFile文件到MinIO
     * @param file Spring MVC文件上传对象
     * @return 生成的文件访问URL（带7天有效期）
     * @throws Exception 文件上传失败或MinIO操作异常
     */
    public String uploadFile(MultipartFile file) throws Exception {
        // 生成唯一文件名（UUID+原始扩展名）
        String originalFilename = file.getOriginalFilename();
        String fileName = generateFileName(originalFilename);

        // 执行MinIO分片上传操作
        minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(bucketName)
                        .object(fileName)
                        .contentType(file.getContentType()) // 保留原始MIME类型
                        .stream(file.getInputStream(), file.getSize(), -1) // -1表示默认分片大小
                        .build()
        );

        return getFileUrl(fileName);
    }

    /**
     * 生成临时访问URL（预签名）
     * @param fileName MinIO存储的文件路径
     * @return 带时效的HTTP访问地址
     * @throws Exception MinIO客户端操作异常
     */
    public String getFileUrl(String fileName) throws Exception {
        // 生成7天有效期的GET请求预签名URL
        return minioClient.getPresignedObjectUrl(
                GetPresignedObjectUrlArgs.builder()
                        .bucket(bucketName)
                        .object(fileName)
                        .method(Method.GET)
                        .expiry(7, TimeUnit.DAYS)
                        .build()
        );
    }

    /**
     * 校验文件是否存在
     * @param fileName 存储路径标识
     * @return true表示文件存在且可访问
     */
    public boolean isFileExist(String fileName) {
        try {
            // 获取文件元数据（不存在会抛出异常）
            minioClient.statObject(
                    StatObjectArgs.builder()
                            .bucket(bucketName)
                            .object(fileName)
                            .build()
            );
            return true;
        } catch (Exception e) {
            // 捕获所有异常（包括文件不存在/权限问题等）
            return false;
        }
    }

    /**
     * 永久删除存储文件
     * @param fileName 需要删除的文件路径
     * @throws Exception 文件删除失败或权限异常
     */
    public void deleteFile(String fileName) throws Exception {
        minioClient.removeObject(
                RemoveObjectArgs.builder()
                        .bucket(bucketName)
                        .object(fileName)
                        .build()
        );
    }

    /**
     * 生成唯一文件名（避免重复覆盖）
     * @param originalFilename 原始文件名（带扩展名）
     * @return UUID字符串+原始扩展名的组合
     */
    private String generateFileName(String originalFilename) {
        String uuid = UUID.randomUUID().toString().replace("-", "");
        String extension = "";

        // 保留原始文件扩展名（如果存在）
        if (originalFilename != null && originalFilename.contains(".")) {
            extension = originalFilename.substring(originalFilename.lastIndexOf("."));
        }
        return uuid + extension;
    }
}